import sensor, image, time,math,screen
from pyb import LED
from pyb import UART

sensor.reset()
sensor.set_pixformat(sensor.GRAYSCALE)#设置摄像头灰度模式
sensor.set_framesize(sensor.QQVGA)#设置分辨率160*120
sensor.set_contrast(3)  #设置对比度，范围-3~3
uart = UART(3, 115200)
red_led=LED(1)
green_led=LED(2)
blue_led=LED(3)


num_quantity=8  #数字的数量
num_model=[]    #存储数字模型图片的列表
#这里的数字图片模型高度40pix
for n in range(1,num_quantity+1):#循环将根目录下F文件夹的数字图片载入
    num_model.append(image.Image('/S/'+str(n)+'.pgm'))

clock = time.clock()    #声明时钟，用于计帧速

screen.init(40)
img_colorful=sensor.alloc_extra_fb(160,120,sensor.GRAYSCALE)   #声明一个彩色画布，用于屏幕显示
img_to_matching=sensor.alloc_extra_fb(35,45,sensor.GRAYSCALE)   #声明小尺寸画布，用于模板匹配
threshold=(0, 70)#找色块阈值

scale=1 #缩放比例变量

#透视变换变量
w = sensor.width()
h = sensor.height()
TARGET_POINTS = [(0,   0),   # (x, y) CHANGE ME!
                 (w-1, 0),   # (x, y) CHANGE ME!
                 (w-1, h-1), # (x, y) CHANGE ME!
                 (0,   h-1)] # (x, y) CHANGE ME!
# Degrees per frame to rotation by...
# 每帧旋转的角度…
X_ROTATION_DEGREE_RATE = 5
Y_ROTATION_DEGREE_RATE = 0.5
Z_ROTATION_DEGREE_RATE = 0
X_OFFSET = 0
Y_OFFSET = 0
ZOOM_AMOUNT = 1 # Lower zooms out - Higher zooms in. 较低的值缩小-较高的放大
FOV_WINDOW = 25 # Between 0 and 180. Represents the field-of-view of the scene
                # window when rotating the image in 3D space. When closer to
                # zero results in lines becoming straighter as the window
                # moves away from the image being rotated in 3D space. A large
                # value moves the window closer to the image in 3D space which
                # results in the more perspective distortion and sometimes
                # the image in 3D intersecting the scene window.
                # 在0和180之间。表示在三维空间中旋转图像时场景窗口的视场。
                # 当接近于0时，随着窗口远离在三维空间中旋转的图像，直线会变得更直。
                # 在三维空间中，较大的值会使窗口更靠近图像，从而导致更多的透视畸变，
                # 有时会导致三维图像与场景窗口相交。
x_rotation_counter = 0
y_rotation_counter = 0
z_rotation_counter = 0
flag_zuo=0 #透视变换标志位
flag_shibei=0

while(True):
    clock.tick()    #用于计帧速，要在循环开头运行一次
    img = sensor.snapshot() #获取摄像头画面
    #img = img.gamma_corr(1.5) # 进行伽马变换，使用软件调节图像的亮度算法
    red_led.on()
    green_led.on()
    blue_led.on()
    blobs = img.find_blobs([threshold]) #按阈值寻找色块，将结果装入blobs。结果可能为多组数据
    if blobs:   #如果blobs有效
     for blob in blobs: #依次循环每个色块
        if blob.pixels()>50 and 100>blob.h()>10 and blob.w()>3:#色块尺寸过滤
            scale=40/blob.h()#通过色块尺寸，计算需要的缩放比例
            #按坐标和比例提取出色块（即摄像头拍到的数字）。注意坐标长宽各扩大4个像素，避免图像不完整。
            img_to_matching.draw_image(img,0,0,roi=(blob.x()-2,blob.y()-2,blob.w()+4,blob.h()+4),x_scale=scale,y_scale=scale)
            for n in range(0,num_quantity):
                #用所有数字模型和它做匹配
                r = img_to_matching.find_template(num_model[n], 0.75, step=2, search=image.SEARCH_EX) #, roi=(10, 0, 60, 60))
                if r:#如果有匹配结果
                    img.draw_rectangle(blob[0:4],color=0)
                    img.draw_string(blob[0],blob[1],str(n+1))
                    num = n+1
                    output_str="target=%d!" % (num)
                    uart.write(output_str)
                    #time.sleep_ms(10)
                    print(num)

    #屏幕显示
    img_colorful.draw_image(img,0,0)
    img_colorful.draw_string(5,5,str(round(clock.fps(),2)))

    screen.display(img_colorful)




###############
'''透视变换，将拍摄的图片进行水平翻转，以便可以识别到放缩的数字，只能将原图进行偏转，对放缩了的图片进行偏转容易识别不到
    if flag_zuo==0:
        z_rotation_counter += 0.5
        if z_rotation_counter==30:
            flag_zuo=1
    elif flag_zuo==1:
        z_rotation_counter -= 0.5
        if z_rotation_counter==-30:
            flag_zuo=2
            z_rotation_counter=0
    img = img.rotation_corr(x_rotation = x_rotation_counter, \
                                          y_rotation = y_rotation_counter, \
                                          z_rotation = z_rotation_counter, \
                                          x_translation = X_OFFSET, \
                                          y_translation = Y_OFFSET, \
                                          zoom = ZOOM_AMOUNT, \
                                          fov = FOV_WINDOW, \
                                          corners = TARGET_POINTS)
'''
'''
                    img_to_matching=img_to_matching.rotation_corr(x_rotation = x_rotation_counter, \
                                                                  y_rotation = y_rotation_counter, \
                                                                  z_rotation = 0, \
                                                                  x_translation = X_OFFSET, \
                                                                  y_translation = Y_OFFSET, \
                                                                  zoom = ZOOM_AMOUNT, \
                                                                  fov = FOV_WINDOW, \
                                                                  corners = TARGET_POINTS)
    img_colorful=img_colorful.rotation_corr(x_rotation = x_rotation_counter, \
                                                                  y_rotation = y_rotation_counter, \
                                                                  z_rotation = 10, \
                                                                  x_translation = X_OFFSET, \
                                                                  y_translation = Y_OFFSET, \
                                                                  zoom = ZOOM_AMOUNT, \
                                                                  fov = FOV_WINDOW, \
                                                                  corners = TARGET_POINTS)
'''
